package DB;

import java.util.ArrayList;
import java.util.HashSet;
import java.util.Iterator;
import java.util.List;
import java.util.Set;

import org.hibernate.Query;
import org.hibernate.Session;
import org.hibernate.SessionFactory;
import org.hibernate.cfg.Configuration;

public class AlgoDB implements AlgoDBMan 
{
	SessionFactory seFac;
	
	public AlgoDB()
	{
		
	}
	
	public AlgoDB(SessionFactory sessionFactory)
	{
		seFac = sessionFactory;
	}

	/**
	 * this function add new algorithm to the table
	 * @param path the path of the algorithm by {@link String}
	 * @return {@link AlgoLoad} an object of the requested algorithm
	 */
	public AlgoLoad addAlg(String path)
	{
		Session se = seFac.openSession();
		AlgoLoad  al = null;
		String sqlQuery="from AlgoLoad where algoPath=:path"; 
		Query query = se.createQuery(sqlQuery).setParameter("path", path.toString());
		if(!query.list().isEmpty())
		{
			List <AlgoLoad>list = query.list();
			Iterator<AlgoLoad> it=list.iterator();
			al = it.next();
		}
		if(al == null)
		{
			al= new AlgoLoad();
			al.setAlgoPath(path);
			al.setChosen(0);
			se.save(al);
			se.flush();
			se.close();
			return al;
		}
		else 
			return null; /* algo already exist */
	}
	
	/**
	 * this function delete requested algorithm from the table
	 * @param path the path of the algorithm by {@link String}
	 * @return {@link Boolean} if the deletion happened or false if not
	 */
	public boolean deleteAlgo(String path)
	{
		Session se = seFac.openSession();
		AlgoLoad  al = null;
		String sqlQuery="from AlgoLoad where algoPath=:path"; 
		Query query = se.createQuery(sqlQuery).setParameter("path", path.toString());
		if(!query.list().isEmpty())
		{
			List <AlgoLoad>list = query.list();
			Iterator<AlgoLoad> it=list.iterator();
			al = it.next();
		}
		if(al != null)
		{
			se.delete(al);
			se.flush();
			se.close();
			return true;
		}
		else
		{
			se.close();
			return false;
		}
	}
	
	/**
	 * this function return all the algorithms from the table
	 * @return {@link ArrayList} with all the paths of the algorithms
	 */
	public ArrayList<String> getAllAlgos()
	{
		Session session = seFac.openSession();
		ArrayList<String> paths = null;
		Query query = session.createQuery("from AlgoLoad");
		if(!query.list().isEmpty())
		{
			paths = new ArrayList<String>();
			List <AlgoLoad>list = query.list();
			Iterator<AlgoLoad> it=list.iterator();
			while(it.hasNext())
				paths.add( it.next().getAlgoPath());
		}
		session.close();
		return paths;
	}
	
	/**
	 * this function return all the algorithms that chosen by the user
	 * @return {@link ArrayList} with all the paths of the algorithms
	 */
	public ArrayList<String> getAllChosenAlgo()
	{
		Session se = seFac.openSession();
		ArrayList<String> paths = null;
		Query query = se.createQuery("from AlgoLoad where chosen = 1");
		if(!query.list().isEmpty())
		{
			paths = new ArrayList<String>();
			List <AlgoLoad>list = query.list();
			Iterator<AlgoLoad> it=list.iterator();
			while(it.hasNext())
				paths.add( it.next().getAlgoPath());
		}
		se.close();
		return paths;
	}
	
	/**
	 * this function update the table according the selection of the user
	 * @param chosenAlgo {@link ArrayList} all the algorithms that the user choose
	 * @return {@link Boolean} true if the operation succeed and false if not
	 */
	public boolean selectNewAlgo(ArrayList<String> chosenAlgo)
	{
		Session se = seFac.openSession();
		ArrayList<String> zero = getAllAlgos();
		zero.removeAll(chosenAlgo);
		Iterator<String> itZ = zero.iterator();
		AlgoLoad  al = null;
		while(itZ.hasNext())
		{
			String sqlQuery="from AlgoLoad where algoPath=:path"; 
			Query query = se.createQuery(sqlQuery).setParameter("path", (itZ.next()).toString());
			if(!query.list().isEmpty())
			{
				List <AlgoLoad>list = query.list();
				Iterator<AlgoLoad> it=list.iterator();
				al = it.next();
			}
			if(al != null)
			{
				al.setChosen(0);
				se.update(al);
				se.flush();
			}
		}
		if(chosenAlgo != null)
		{
			Iterator<String> itO = chosenAlgo.iterator();
			while(itO.hasNext())
			{
				String sqlQuery="from AlgoLoad where algoPath=:path"; 
				Query query = se.createQuery(sqlQuery).setParameter("path", (itO.next()).toString());
				if(!query.list().isEmpty())
				{
					List <AlgoLoad>list = query.list();
					Iterator<AlgoLoad> it=list.iterator();
					al = it.next();
				}
				if(al != null)
				{
					al.setChosen(1);
					se.update(al);
					se.flush();
				}
			}
		}
		se.close();
		return true;
	}
	
	/**
	 * this function add new algorithms to the table
	 * @param paths {@link ArrayList} of all the algorithms that the user add to the system
	 * @return {@link Boolean} true if the operation succeed and false if not
	 */
	public boolean addSomeAlg(ArrayList<String> paths)
	{
		int flag = 0;
		Session se = seFac.openSession();
		AlgoLoad  al = null;
		Iterator<String> iter = paths.iterator();
		while(iter.hasNext())
		{
			String path = iter.next();
			String sqlQuery="from AlgoLoad where algoPath=:path"; 
			Query query = se.createQuery(sqlQuery).setParameter("path", path.toString());
			if(!query.list().isEmpty())
			{
				List <AlgoLoad>list = query.list();
				Iterator<AlgoLoad> it=list.iterator();
				al = it.next();
			}
			if(al == null)
			{
				al= new AlgoLoad();
				al.setAlgoPath(path);
				al.setChosen(0);
				se.save(al);
				se.flush();
				flag = 1;
			}
		}
		se.close();
		if(flag == 1)
			return true;
		else 
			return false; /* algorithms are already exist */
	}
	
}
